package com.backend.thread.reentrantLock

import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

/**
 * 实现一个简单的并发消息缓存队列。
 */
class SimpleMessageBuffer {
    private val lock: Lock = ReentrantLock(false)// 锁对象
    private val notFull = lock.newCondition()// 写线程条件。未满才可以写。
    private val notEmpty = lock.newCondition()// 读线程条件。非空才可以读。

    private val items = arrayOfNulls<Int>(5)// 缓存队列数据存储区。
    private var putOffset: Int = 0/* 可写的位置 */
    private var takeOffset: Int = 0/* 可读的位置 */
    private var count: Int = 0 /* 队列中当前数据个数 */

    @Throws(InterruptedException::class)
    fun put(x: Int) {
        lock.lock()
        try {
            while (count == items.size){
                // 如果队列满了
                notFull.await()// 阻塞写线程
            }
            items[putOffset] = x// 赋值
            println("写入：" + x)
            if (++putOffset == items.size)
                putOffset = 0// 如果写索引写到队列的最后一个位置了，那么置为0
            ++count// 个数++
            notEmpty.signal()// 唤醒读线程
        } finally {
            lock.unlock()
        }
    }

    @Throws(InterruptedException::class)
    fun take(): Int {
        lock.lock()
        try {
            while (count == 0){
                // 如果队列为空
                notEmpty.await()// 阻塞读线程
            }
            val x = items[takeOffset]// 取值
            println("读取：" + x)
            if (++takeOffset == items.size)
                takeOffset = 0// 如果读索引读到队列的最后一个位置了，那么置为0
            --count// 个数--
            notFull.signal()// 唤醒写线程
            return x?: -1
        } finally {
            lock.unlock()
        }
    }
}